package com.googlecode.perfectable.visuable.entry;

import java.io.IOException;
import java.io.PrintWriter;

import javax.annotation.Nullable;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.googlecode.perfectable.eventable.routing.Sink;
import com.googlecode.perfectable.eventable.routing.Source;
import com.googlecode.perfectable.prosperable.entry.ChannelManager;
import com.googlecode.perfectable.prosperable.message.ClientMessage;
import com.googlecode.perfectable.prosperable.message.ServerMessage;
import com.googlecode.perfectable.visuable.configuration.ConfigurationListener;
import com.googlecode.perfectable.visuable.configuration.Configurator;
import com.googlecode.perfectable.visuable.screen.Screen;
import com.googlecode.perfectable.visuable.screen.ScreenFactory;
import com.googlecode.perfectable.visuable.screen.StandardScreenFactory;

public class EntryServlet extends HttpServlet {
	private static final long serialVersionUID = -4609382746561846927L;

	private static final String SCREEN_RESOURCE_PARAMETER = "initialScreenResource";

	private ScreenFactory screenFactory;

	@Override
	public void init() throws ServletException {
		final ServletContext servletContext = getServletContext();
		String screenResourceName = getServletConfig().getInitParameter(SCREEN_RESOURCE_PARAMETER);
		if(screenResourceName == null) {
			screenResourceName = servletContext.getInitParameter(SCREEN_RESOURCE_PARAMETER);
		}
		if(screenResourceName == null) {
			throw new ServletException("empty " + SCREEN_RESOURCE_PARAMETER + " parameter in init");
		}
		Configurator configurator = ConfigurationListener.extractConfigurator(servletContext);
		this.screenFactory = new StandardScreenFactory(configurator, screenResourceName);
	}

	@Override
	protected void doGet(@Nullable HttpServletRequest req, @Nullable HttpServletResponse resp)
			throws ServletException, IOException {
		if(req == null || resp == null) {
			throw new ServletException();
		}
		Screen screen = extractScreen(req);
		try(PrintWriter writer = resp.getWriter()) {
			if(writer == null) {
				throw new ServletException();
			}
			screen.write(writer);
		}
		resp.setStatus(200);
	}

	protected Screen extractScreen(HttpServletRequest req) {
		final HttpSession session = req.getSession();
		if(session == null) {
			throw new IllegalStateException();
		}
		Source<ClientMessage> inboundMessageSource = ChannelManager.extractInbound(session);
		Sink<ServerMessage> outboundMessageSink = ChannelManager.extractOutbound(session);
		Screen screen = this.screenFactory.create(inboundMessageSource, outboundMessageSink);
		return screen;
	}
}
